package com.yanqu.road.server.manager.beautyescort;

import com.yanqu.road.entity.beautyescort.*;
import com.yanqu.road.entity.beautyescort.enums.eEscortCartState;
import com.yanqu.road.entity.player.UserBaseInfo;
import com.yanqu.road.entity.rank.cross.CrossUnionWeekRank;
import com.yanqu.road.logic.bussiness.beautyescort.BeautyEscortBussiness;
import com.yanqu.road.logic.config.GameConfig;
import com.yanqu.road.logic.pb.PlayerBasePb;
import com.yanqu.road.logic.pb.UnionBasePb;
import com.yanqu.road.pb.beautyescort.BeautyEscortProto;
import com.yanqu.road.pb.union.cross.CrossUnionProto;
import com.yanqu.road.server.TempMgr;
import com.yanqu.road.server.logic.MessageHelper;
import com.yanqu.road.server.manager.user.CrossUserMgr;
import com.yanqu.road.server.manger.ConfigMgr;
import com.yanqu.road.sync.message.SyncResponse;
import com.yanqu.road.utils.YanQuMessageUtils;
import com.yanqu.road.server.protocol.Protocol;
import com.yanqu.road.utils.date.DateHelper;
import com.yanqu.road.utils.property.Property;
import com.yanqu.road.utils.property.PropertyHelper;
import com.yanqu.road.utils.string.StringUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ConcurrentHashMap;

public class CrossBeautyEscortMgr extends TempMgr {

    private static Logger logger = LogManager.getLogger(CrossBeautyEscortMgr.class.getName());

    /**
     * serverId：userId:
     */
    static Map<Long, Map<Long, CrossEscortPlayerWrap>> escortPlayerMap = new ConcurrentHashMap<>();

    /**
     * userId：serverId   缓存
     */
    static Map<Long, Long> userServerMap = new ConcurrentHashMap<>();

    /**
     * 玩家锁
     */
    private static Map<Long, Object> userLockerMap = new ConcurrentHashMap<>();

    /**
     * 商会战报数
     */
    public static int UNION_REPORT_NUM = 100;

    /**
     * 个人战报数
     */
    public static int MY_REPORT_NUM = 50;

    /**
     * 地图位置数量
     */
    public static int ROAD_MAP_POSITION_NUM = 27;

    @Override
    public boolean reloadConfig() throws Exception {
        return true;
    }

    @Override
    public boolean reloadData() throws Exception {
        initEscortDataFromDb();
        return true;
    }

    /**
     * 从数据库初始数据
     */
    public static void initEscortDataFromDb() {
        int thisWeekId = CrossBeautyEscortRankMgr.getThisWeekId();
        Map<Long, EscortUserData> userDataMap = BeautyEscortBussiness.getEscortUserDataMap();
        Map<Long, Map<Integer, EscortCartData>> escortCartDataMap = BeautyEscortBussiness.getEscortCartDataMap();
        Map<Long, Map<Long, EscortReport>> escortReportDataMap = BeautyEscortBussiness.getEscortReportMap(thisWeekId);
        synchronized (escortPlayerMap){
            Map<Long, Map<Long, CrossEscortPlayerWrap>> tempEscortPlayerMap = new ConcurrentHashMap<>();
            for (EscortUserData userData : userDataMap.values()) {
                CrossEscortPlayerWrap escortPlayerWrap = new CrossEscortPlayerWrap();
                escortPlayerWrap.setUserData(userData);
                UserBaseInfo userBaseInfo = CrossUserMgr.getUserBaseInfo(userData.getUserId());
                escortPlayerWrap.setUserBaseInfo(userBaseInfo);

                if(escortCartDataMap.containsKey(userData.getUserId())){
                    escortPlayerWrap.setCartDataMap(escortCartDataMap.get(userData.getUserId()));
                }
                if(escortReportDataMap.containsKey(userData.getUserId())){
                    escortPlayerWrap.setEscortReportMap(escortReportDataMap.get(userData.getUserId()));
                }
                if(!tempEscortPlayerMap.containsKey(userData.getServerId())){
                    tempEscortPlayerMap.put(userData.getServerId(), new ConcurrentHashMap<>());
                }
                tempEscortPlayerMap.get(userData.getServerId()).put(userData.getUserId(), escortPlayerWrap);
                userServerMap.put(userData.getUserId(), userData.getServerId());
            }
            escortPlayerMap = tempEscortPlayerMap;
        }
    }

    @Override
    public boolean init() throws Exception {
        return reload();
    }

    @Override
    public boolean stop() {
        return false;
    }

    @Override
    public boolean save() {
        for (Map.Entry<Long, Map<Long, CrossEscortPlayerWrap>> mapEntry : escortPlayerMap.entrySet()) {
            for (Map.Entry<Long, CrossEscortPlayerWrap> playerWrapEntry : mapEntry.getValue().entrySet()) {
                CrossEscortPlayerWrap playerWrap = playerWrapEntry.getValue();
                playerWrap.save();
            }
        }
        return true;
    }

    /**
     * 获取玩家数据
     */
    public static CrossEscortPlayerWrap getEscortPlayer(long serverId, long userId){
        Map<Long, CrossEscortPlayerWrap> map = escortPlayerMap.get(serverId);
        if(map == null){
            return null;
        }
        return map.get(userId);
    }

    /**
     * 获取玩家
     */
    public static CrossEscortPlayerWrap getEscortPlayer(long userId){
        if(userServerMap.containsKey(userId)){
            long serverId = userServerMap.get(userId);
            return getEscortPlayer(serverId, userId);
        }else {
            for (Map.Entry<Long, Map<Long, CrossEscortPlayerWrap>> serverEntry : escortPlayerMap.entrySet()) {
                for (Map.Entry<Long, CrossEscortPlayerWrap> userEntry : serverEntry.getValue().entrySet()) {
                    if(userId == userEntry.getKey()){
                        userServerMap.put(userEntry.getKey(), serverEntry.getKey());
                        return userEntry.getValue();
                    }
                }
            }
        }
        return null;
    }

    /**
     * 获取玩家所在区服
     */
    public static long getUserServerId(long userId){
        if(userServerMap.containsKey(userId)){
            return userServerMap.get(userId);
        }else {
            for (Map.Entry<Long, Map<Long, CrossEscortPlayerWrap>> serverEntry : escortPlayerMap.entrySet()) {
                for (Map.Entry<Long, CrossEscortPlayerWrap> userEntry : serverEntry.getValue().entrySet()) {
                    if(userId == userEntry.getKey()){
                        userServerMap.put(userEntry.getKey(), serverEntry.getKey());
                        return serverEntry.getKey();
                    }
                }
            }
        }
        return 0;
    }

    /**
     * 获取区服所有玩家
     */
    public static Map<Long, CrossEscortPlayerWrap> getAllEscortPlayer(long serverId){
        return escortPlayerMap.get(serverId);
    }

    /**
     * 初始玩家数据
     */
    public static CrossEscortPlayerWrap initEscortPlayer(long serverId, long userId, UserBaseInfo userBaseInfo){
        if(!escortPlayerMap.containsKey(serverId)){
            synchronized (escortPlayerMap){
                if(!escortPlayerMap.containsKey(serverId)){
                    escortPlayerMap.put(serverId, new ConcurrentHashMap<>());
                }
            }
        }
        Map<Long, CrossEscortPlayerWrap> playerMap = escortPlayerMap.get(serverId);
        if(!playerMap.containsKey(userId)){
            synchronized (getUserLocker(userId)) {
                if(!playerMap.containsKey(userId)){
                    EscortUserData userData = new EscortUserData();
                    userData.setServerId(serverId);
                    userData.setUserId(userId);
                    userData.setResetTime(System.currentTimeMillis());
                    userData.setInsertOption();
                    CrossEscortPlayerWrap escortPlayer = new CrossEscortPlayerWrap(userData, userBaseInfo);
                    //初始镖车数据
                    for(int i = 0; i < 3; i++){
                        EscortCartData cartData = new EscortCartData();
                        cartData.setUserId(userId);
                        cartData.setServerId(serverId);
                        cartData.setCartId(i+1);
                        cartData.setInsertOption();
                        escortPlayer.getCartDataMap().put(cartData.getCartId(), cartData);
                    }
                    playerMap.put(userId, escortPlayer);
                    userServerMap.put(userId, serverId);
                }
            }
        }
        return playerMap.get(userId);
    }

    /**
     * 随机同一分组玩家
     */
    public static List<CrossEscortPlayerWrap> randomRoadMapPlayerInGroup(long serverId, long userId, String unionUid, List<Long> hasUserId) {
        //发起玩家
        CrossEscortPlayerWrap playerWrap = CrossBeautyEscortMgr.getEscortPlayer(serverId, userId);

        List<Long> serverIdList = CrossBeautyEscortRankMgr.getGroupServer(serverId);
        List<CrossEscortPlayerWrap> all = new ArrayList<>();
        for(long sid : serverIdList){
            all.addAll(randomRoadMapPlayerInServer(sid, userId, unionUid, serverId, hasUserId));
        }

        if(all.size() <= GameConfig.ESCORT_ROAD_MAP_SELECT_POOL_SIZE){
            return all;
        }

        List<CrossEscortPlayerWrap> warpList = getSortCrossEscortPlayerWraps(playerWrap, all, GameConfig.ESCORT_ROAD_MAP_SELECT_POOL_SIZE);
        return  warpList;
    }

    /**
     * 随机区服玩家
     */
    public static List<CrossEscortPlayerWrap> randomRoadMapPlayerInServer(long serverId, long userId, String unionUid, long userServerId, List<Long> hasUserId) {
        //发起玩家
        CrossEscortPlayerWrap playerWrap = CrossBeautyEscortMgr.getEscortPlayer(userServerId, userId);
        //待随机玩家集合
        Map<Long, CrossEscortPlayerWrap> playerWrapMap = CrossBeautyEscortMgr.getAllEscortPlayer(serverId);
        if(playerWrapMap == null){
            return new ArrayList<>();
        }
        List<CrossEscortPlayerWrap> userList = new ArrayList<>();
        if(serverId == userServerId){
            //同区服
            for (Map.Entry<Long, CrossEscortPlayerWrap> wrapEntry : playerWrapMap.entrySet()) {
                if(hasUserId.contains(wrapEntry.getKey())){
                    continue;
                }
                if(wrapEntry.getKey() == userId){
                    continue;
                }
                if(wrapEntry.getValue().getUserBaseInfo() == null){
                    continue;
                }
                if(unionUid.equals(wrapEntry.getValue().getUserBaseInfo().getUnionUid())){
                    continue;
                }
                if(wrapEntry.getValue().canRob(ConfigMgr.getMaxRobTimesInLoss(), userId) == null){
                    continue;
                }
                userList.add(wrapEntry.getValue());
            }
        }else {
            for (Map.Entry<Long, CrossEscortPlayerWrap> wrapEntry : playerWrapMap.entrySet()) {
                if(hasUserId.contains(wrapEntry.getKey())){
                    continue;
                }
                if(unionUid.equals(wrapEntry.getValue().getUserBaseInfo().getUnionUid())){
                    continue;
                }
                if(wrapEntry.getValue().canRob(ConfigMgr.getMaxRobTimesInLoss(), userId) == null){
                    continue;
                }
                userList.add(wrapEntry.getValue());
            }
        }
        if(userList.size() <= GameConfig.ESCORT_ROAD_MAP_SELECT_POOL_SIZE){
            return userList;
        }
        List<CrossEscortPlayerWrap> warpList = getSortCrossEscortPlayerWraps(playerWrap, userList, GameConfig.ESCORT_ROAD_MAP_SELECT_POOL_SIZE);
        return warpList;
    }

    /**
     * 按魅力排序获取最相近的玩家
     */
    private static List<CrossEscortPlayerWrap> getSortCrossEscortPlayerWraps(CrossEscortPlayerWrap playerWrap, List<CrossEscortPlayerWrap> userList, int num) {
        List<CrossEscortPlayerWrap> warpList = new ArrayList<>();
        //按魅力值排序
        userList.sort(new Comparator<CrossEscortPlayerWrap>() {
            @Override
            public int compare(CrossEscortPlayerWrap o1, CrossEscortPlayerWrap o2) {
                long l = Math.abs(o1.getUserData().getTotalGlamour() - playerWrap.getUserData().getTotalGlamour()) - Math.abs(o2.getUserData().getTotalGlamour() - playerWrap.getUserData().getTotalGlamour());
                if (l > 0) {
                    return 1;
                }
                if (l < 0) {
                    return -1;
                }
                return 0;
            }
        });
        warpList.addAll(userList.subList(0, Math.min(num, userList.size() - 1)));
        return warpList;
    }

    public static Map<Long, List<Integer>> getAllMemberAttackRecordMap(String unionUid, CrossEscortPlayerWrap playerWrap, List<Long> memberList){
        //玩家攻击的对象
        Map<Long, List<Integer>> attackRecordMap = new HashMap<>();

        long serverId = playerWrap.getUserData().getServerId();

        //只遍历商会成员
        for (long sid : CrossBeautyEscortRankMgr.getGroupServer(serverId)) {
            Map<Long, CrossEscortPlayerWrap> tempMap = getAllEscortPlayer(sid);
            if(tempMap == null){
                continue;
            }
            for (Long memberId : memberList) {
                CrossEscortPlayerWrap escortPlayerWrap = tempMap.get(memberId);
                if(escortPlayerWrap == null){
                    continue;
                }
                //过滤不活跃的玩家
                if (escortPlayerWrap.getUserBaseInfo() == null) {
                    continue;
                }
                if (!unionUid.equals(escortPlayerWrap.getUserBaseInfo().getUnionUid())) {
                    continue;
                }
                //商会攻击的对象
                EscortUserData memberUserData = escortPlayerWrap.getUserData();
                for (Map.Entry<Long, EscortAttackRecord> recordEntry : memberUserData.getAttackRecord().entrySet()) {
                    long enemy = recordEntry.getKey();
                    if(attackRecordMap.containsKey(enemy)){
                        attackRecordMap.get(enemy).addAll(recordEntry.getValue().getTime());
                    }else {
                        attackRecordMap.put(enemy, new ArrayList<>(recordEntry.getValue().getTime()));
                    }
                }
            }
        }
        return attackRecordMap;
    }

    /**
     * 获取战报
     */
    public static void getRobbedReport(long serverId, long playerId, int type, long dartId, List<Long> memberList) {
        CrossEscortPlayerWrap playerWrap = getEscortPlayer(serverId, playerId);
        String unionUid = playerWrap.getUserBaseInfo().getUnionUid();
        List<EscortReport> reportList = new ArrayList<>();
        int thisWeekId = CrossBeautyEscortRankMgr.getThisWeekId();
        int second = DateHelper.getCurrentSecond();
        int gap = 4 * 3600; //4小时，上周距离本周4小时内走镖的要显示

        //所有成员攻击过的对手
        Map<Long, List<Integer>> attackRecordMap = getAllMemberAttackRecordMap(unionUid, playerWrap, memberList);

        if(type == 0) {
            for (Map.Entry<Long, EscortReport> reportEntry : playerWrap.getEscortReportList()) {
                EscortReport report = reportEntry.getValue();
                if(dartId > 0 && report.getDartId() != dartId){
                    continue;
                }
                if(report.getWeekId() < thisWeekId && second - report.getStartTime() > gap){
                    continue;
                }
                reportList.add(report);
            }
        }else {

            //只遍历商会成员
            for (long sid : CrossBeautyEscortRankMgr.getGroupServer(serverId)) {
                Map<Long, CrossEscortPlayerWrap> tempMap = getAllEscortPlayer(sid);
                if (tempMap == null) {
                    continue;
                }
                for (Long memberId : memberList) {
                    if(memberId == playerId){
                        continue;
                    }
                    CrossEscortPlayerWrap escortPlayerWrap = tempMap.get(memberId);
                    if (escortPlayerWrap == null) {
                        continue;
                    }
                    if(escortPlayerWrap.getUserBaseInfo() == null){
                        continue;
                    }
                    if(!unionUid.equals(escortPlayerWrap.getUserBaseInfo().getUnionUid())){
                        continue;
                    }
                    for (Map.Entry<Long, EscortReport> reportEntry : escortPlayerWrap.getEscortReportList()) {
                        EscortReport report = reportEntry.getValue();
                        if(report.getWeekId() < thisWeekId && second - report.getStartTime() > gap){
                            continue;
                        }
                        if(report.getLatestRobTime() > escortPlayerWrap.getUserData().getParams().getJoinUnionTime()) {
                            reportList.add(report);
                        }
                    }
                }
            }
        }

        reportList.sort((o1, o2) -> o2.getLatestRobTime() - o1.getLatestRobTime());
        int num = MY_REPORT_NUM;
        if(type == 1){
            num = UNION_REPORT_NUM;
        }
        while (reportList.size() > num){
            EscortReport report = reportList.remove(reportList.size() - 1);
            //标记移除个人战报
            if(type == 0){
                report.setDel(true);
            }
        }

        BeautyEscortProto.BeautyEscortReportRespMsg.Builder respMsg = BeautyEscortProto.BeautyEscortReportRespMsg.newBuilder();
        respMsg.setRet(0);
        respMsg.setType(type);
        int now = DateHelper.getCurrentSecond();

        //先拉取所有商会及成员
        List<String> unionUidList = new ArrayList<>();
        for (EscortReport report : reportList) {
            for (EnemyInfo enemyInfo : report.getEnemyInfoList()) {
                CrossEscortPlayerWrap reportPlayer = getEscortPlayer(enemyInfo.getUserId());
                if(reportPlayer == null){
                    continue;
                }
                UserBaseInfo userBaseInfo = reportPlayer.getUserBaseInfo();
                if(userBaseInfo == null || StringUtils.isNullOrEmpty(userBaseInfo.getUnionUid())){
                    getLogger().info("{} 无商会", enemyInfo.getUserId());
                    continue;
                }
                if(!unionUidList.contains(userBaseInfo.getUnionUid())){
                    unionUidList.add(userBaseInfo.getUnionUid());
                }
            }
        }

        if(unionUidList.size() > 0){
            CrossUnionProto.CrossGetUnionMemberIdRespMsg.Builder bmsg = CrossUnionProto.CrossGetUnionMemberIdRespMsg.newBuilder();
            CrossUnionProto.CrossGetUnionMemberIdReqMsg.Builder sendMsg = CrossUnionProto.CrossGetUnionMemberIdReqMsg.newBuilder();
            sendMsg.addAllUnionUid(unionUidList);
            CompletableFuture<SyncResponse> responseFuture = MessageHelper.sendToCross3Server(serverId, Protocol.C3_UNION_GET_UNION_MEMBER_USER_ID, 0, 0, sendMsg, bmsg);
            responseFuture.thenAccept( response -> {
                if (response.getErrorCode() == 0) {
                    Map<String, List<Long>> unionMemberList = new HashMap<>();
                    for (CrossUnionProto.CrossUnionMemberListTemp listTemp : bmsg.getMemberList()) {
                        unionMemberList.put(listTemp.getUnionUid(), listTemp.getUserIdList());
                    }
                    for (EscortReport report : reportList) {
                        BeautyEscortProto.BeautyEscortReportTemp.Builder reportBuilder = BeautyEscortProto.BeautyEscortReportTemp.newBuilder();
                        reportBuilder.setUserId(report.getUserId());
                        CrossEscortPlayerWrap player = getEscortPlayer(report.getServerId(), report.getUserId());
                        reportBuilder.setNickName(player.getUserBaseInfo().getNickName());
                        reportBuilder.setTime(report.getLatestRobTime());
                        //反向查找玩家的镖车
                        CrossEscortPlayerWrap crossEscortPlayerWrap = getEscortPlayer(report.getServerId(), report.getUserId());
                        reportBuilder.setDecoration(crossEscortPlayerWrap.getUserBaseInfo().getDecoration());
                        EscortCartData cartData = crossEscortPlayerWrap.getCartDataByDartId(report.getDartId());
                        if(cartData != null){
                            reportBuilder.setCartState(cartData.getState());
                            reportBuilder.setReward(getRobbedLose(cartData.getDartTypeId(), cartData.getRobbedTimes()));
                        }else {
                            reportBuilder.setCartState(eEscortCartState.Finish.getIntValue());
                            if(report.getRobbedTimes() > 0) {
                                reportBuilder.setReward(getRobbedLose(report.getDartType(), report.getRobbedTimes()));
                            }
                        }
                        reportBuilder.setDartType(report.getDartType());
                        reportBuilder.setDartId(report.getDartId());
                        if(type == 1){
                            reportBuilder.setUserInfo(PlayerBasePb.parsePlayerBaseTempMsg(player.getUserBaseInfo()));
                        }
                        for (EnemyInfo enemyInfo : report.getEnemyInfoList()) {
                            CrossEscortPlayerWrap reportPlayer = getEscortPlayer(enemyInfo.getUserId());
                            if(reportPlayer != null) {
                                BeautyEscortProto.BeautyEscortRobUserTemp.Builder userBuilder = BeautyEscortProto.BeautyEscortRobUserTemp.newBuilder();
                                userBuilder.setUserId(enemyInfo.getUserId());
                                //根据反击详情设定是否可反击
                                if(report.getBeatBack().containsKey(enemyInfo.getUserId())){
                                    userBuilder.setBeatBack(true);
                                    userBuilder.setCanRob(false);
                                }else {
                                    userBuilder.setBeatBack(false);
                                    userBuilder.setCanRob(reportPlayer.canRob(ConfigMgr.getMaxRobTimesInLoss(), playerWrap.getUserData().getUserId()) != null);
                                }
                                userBuilder.setDecoration(reportPlayer.getUserBaseInfo().getDecoration());
                                userBuilder.setServerId(reportPlayer.getUserData().getServerId());
                                userBuilder.setUserAliasId(reportPlayer.getUserBaseInfo().getUserAliasId());
                                userBuilder.setTime(enemyInfo.getTime());

                                List<Long> enemyMemberList = new ArrayList<>(unionMemberList.getOrDefault(reportPlayer.getUserBaseInfo().getUnionUid(), Collections.emptyList()));
                                Map<Long, List<Integer>> beAttackRecordMap = getAllMemberAttackRecordMap(reportPlayer.getUserBaseInfo().getUnionUid(), reportPlayer, enemyMemberList);

                                int beatToTime = getEarliestRobTime(now, getAllMemberAttackRecordMap(attackRecordMap, enemyMemberList));
                                int beatBackTime = getEarliestRobTime(now, getAllMemberAttackRecordMap(beAttackRecordMap, memberList));

                                if(beatToTime > 0){
                                    if(beatBackTime <= 0 || beatToTime < beatBackTime){
                                        userBuilder.setBeat(true);
                                    }else {
                                        userBuilder.setBeat(false);
                                    }
                                }else {
                                    userBuilder.setBeat(false);
                                }
                                reportBuilder.addRobUser(userBuilder);
                            }
                        }
                        respMsg.addReport(reportBuilder);
                    }
                    MessageHelper.sendPacket(serverId, playerId, YanQuMessageUtils.buildMessage(Protocol.U_BEAUTY_ESCORT_ROB_REPORT, respMsg));
                }else {
                    MessageHelper.sendPacket(serverId, playerId, YanQuMessageUtils.buildMessage(Protocol.U_BEAUTY_ESCORT_ROB_REPORT, respMsg));
                }
            });


        }else {
            Map<String, List<Long>> unionMemberList = new HashMap<>();
            for (EscortReport report : reportList) {
                BeautyEscortProto.BeautyEscortReportTemp.Builder reportBuilder = BeautyEscortProto.BeautyEscortReportTemp.newBuilder();
                reportBuilder.setUserId(report.getUserId());
                CrossEscortPlayerWrap player = getEscortPlayer(report.getServerId(), report.getUserId());
                reportBuilder.setNickName(player.getUserBaseInfo().getNickName());
                reportBuilder.setTime(report.getLatestRobTime());
                //反向查找玩家的镖车
                CrossEscortPlayerWrap crossEscortPlayerWrap = getEscortPlayer(report.getServerId(), report.getUserId());
                reportBuilder.setDecoration(crossEscortPlayerWrap.getUserBaseInfo().getDecoration());
                EscortCartData cartData = crossEscortPlayerWrap.getCartDataByDartId(report.getDartId());
                if(cartData != null){
                    reportBuilder.setCartState(cartData.getState());
                    reportBuilder.setReward(getRobbedLose(cartData.getDartTypeId(), cartData.getRobbedTimes()));
                }else {
                    reportBuilder.setCartState(eEscortCartState.Finish.getIntValue());
                    if(report.getRobbedTimes() > 0) {
                        reportBuilder.setReward(getRobbedLose(report.getDartType(), report.getRobbedTimes()));
                    }
                }
                reportBuilder.setDartType(report.getDartType());
                reportBuilder.setDartId(report.getDartId());
                if(type == 1){
                    reportBuilder.setUserInfo(PlayerBasePb.parsePlayerBaseTempMsg(player.getUserBaseInfo()));
                }
                for (EnemyInfo enemyInfo : report.getEnemyInfoList()) {
                    CrossEscortPlayerWrap reportPlayer = getEscortPlayer(enemyInfo.getUserId());
                    if(reportPlayer != null) {
                        BeautyEscortProto.BeautyEscortRobUserTemp.Builder userBuilder = BeautyEscortProto.BeautyEscortRobUserTemp.newBuilder();
                        userBuilder.setUserId(enemyInfo.getUserId());
                        //根据反击详情设定是否可反击
                        if(report.getBeatBack().containsKey(enemyInfo.getUserId())){
                            userBuilder.setBeatBack(true);
                            userBuilder.setCanRob(false);
                        }else {
                            userBuilder.setBeatBack(false);
                            userBuilder.setCanRob(reportPlayer.canRob(ConfigMgr.getMaxRobTimesInLoss(), playerWrap.getUserData().getUserId()) != null);
                        }
                        userBuilder.setDecoration(reportPlayer.getUserBaseInfo().getDecoration());
                        userBuilder.setServerId(reportPlayer.getUserData().getServerId());
                        userBuilder.setUserAliasId(reportPlayer.getUserBaseInfo().getUserAliasId());
                        userBuilder.setTime(enemyInfo.getTime());

                        List<Long> enemyMemberList = new ArrayList<>(unionMemberList.getOrDefault(reportPlayer.getUserBaseInfo().getUnionUid(), Collections.emptyList()));
                        Map<Long, List<Integer>> beAttackRecordMap = getAllMemberAttackRecordMap(reportPlayer.getUserBaseInfo().getUnionUid(), reportPlayer, enemyMemberList);

                        int beatToTime = getEarliestRobTime(now, getAllMemberAttackRecordMap(attackRecordMap, enemyMemberList));
                        int beatBackTime = getEarliestRobTime(now, getAllMemberAttackRecordMap(beAttackRecordMap, memberList));

                        if(beatToTime > 0){
                            if(beatBackTime <= 0 || beatToTime < beatBackTime){
                                userBuilder.setBeat(true);
                            }else {
                                userBuilder.setBeat(false);
                            }
                        }else {
                            userBuilder.setBeat(false);
                        }
                        reportBuilder.addRobUser(userBuilder);
                    }
                }
                respMsg.addReport(reportBuilder);
            }

            MessageHelper.sendPacket(serverId, playerId, YanQuMessageUtils.buildMessage(Protocol.U_BEAUTY_ESCORT_ROB_REPORT, respMsg));
        }
    }

    private static List<Integer> getAllMemberAttackRecordMap(Map<Long, List<Integer>> attackRecordMap, List<Long> enemyMemberList) {
        List<Integer> result = new ArrayList<>();
        for (long enemy : enemyMemberList) {
            if(attackRecordMap.containsKey(enemy)){
                result.addAll(attackRecordMap.get(enemy));
            }
        }
        return result;
    }

    public static int getEarliestRobTime(int now, List<Integer> times){
        if(times == null){
            return 0;
        }
        int time = 0;
        long gap = GameConfig.ESCORT_FIGHT_BACK_CONDITION * DateHelper.HOUR_SECONDS;
        for (int t : times) {
            //24小时内
            if(now - t < gap && (time == 0 || time > t)){
                time = t;
            }
        }
        return time;
    }

    /**
     * 根据userAliasId查找玩家
     */
    public static CrossEscortPlayerWrap searchUserByAliasId(long userServerId, long userAliasId) {
        Map<Long, CrossEscortPlayerWrap> userMap = getAllEscortPlayer(userServerId);
        if(userMap == null){
            return null;
        }
        for (Map.Entry<Long, CrossEscortPlayerWrap> wrapEntry : userMap.entrySet()) {
            if(wrapEntry.getValue().getUserBaseInfo() == null){
                continue;
            }
            if(userAliasId == wrapEntry.getValue().getUserBaseInfo().getUserAliasId()){
                return wrapEntry.getValue();
            }
        }
        return null;
    }

    public static String getRobbedLose(int dartType, int robbedTimes){
        EscortDartTypeInfo typeInfo = ConfigMgr.getDartTypeInfoMap().get(dartType);
        Property lose = PropertyHelper.parseStringToProperty(typeInfo.getRewards());
        //被劫损失
        lose.rideProperty(ConfigMgr.getRobbedLossRatio().multiply(BigDecimal.valueOf(robbedTimes)));
        return PropertyHelper.parsePropertyToString(lose);
    }

    /**
     * 获取玩家锁
     */
    public static Object getUserLocker(long userId){
        if(!userLockerMap.containsKey(userId)){
            synchronized (userLockerMap){
                if(!userLockerMap.containsKey(userId)){
                    userLockerMap.put(userId, new Object());
                }
            }
        }
        return userLockerMap.get(userId);
    }

    /**
     * 检测走镖状态（包括事件），定时器调用
     */
    public static boolean checkAllCartState() {
        long startTimeMillis = System.currentTimeMillis();
        for (Map.Entry<Long, Map<Long, CrossEscortPlayerWrap>> serverMapEntry : escortPlayerMap.entrySet()) {
            for (Map.Entry<Long, CrossEscortPlayerWrap> playerWrapEntry : serverMapEntry.getValue().entrySet()) {
                //走镖状态（包括事件）
                playerWrapEntry.getValue().calAllCartStateWithEvent();
            }
        }
        logger.info("cal all beauty escort cart state cost {}", DateHelper.getCurrentTime() - startTimeMillis);
        return true;
    }

    //builder ----------------------------------------

    public static List<EscortBeautyDispatch> parseBeautyDispatch(List<BeautyEscortProto.BeautyEscortBeautyDispatchDataTemp> tempList){
        List<EscortBeautyDispatch> result = new ArrayList<>();
        for(BeautyEscortProto.BeautyEscortBeautyDispatchDataTemp temp : tempList) {
            EscortBeautyDispatch dispatch = new EscortBeautyDispatch();
            dispatch.setBeautyId(temp.getBeautyId());
            dispatch.setGlamour(temp.getGlamour());
            dispatch.setLeftDispatchTime(temp.getLeftDispatchTime());
            result.add(dispatch);
        }
        return result;
    }

    public static List<BeautyEscortProto.BeautyEscortBeautyDispatchDataTemp> parseBeautyDispatchBuilderList(List<EscortBeautyDispatch> dispatchList){
        List<BeautyEscortProto.BeautyEscortBeautyDispatchDataTemp> list = new ArrayList<>(dispatchList.size());
        for (EscortBeautyDispatch dispatch : dispatchList) {
            BeautyEscortProto.BeautyEscortBeautyDispatchDataTemp.Builder builder = BeautyEscortProto.BeautyEscortBeautyDispatchDataTemp.newBuilder();
            builder.setBeautyId(dispatch.getBeautyId());
            builder.setGlamour(dispatch.getGlamour());
            builder.setLeftDispatchTime(dispatch.getLeftDispatchTime());
            list.add(builder.build());
        }
        return list;
    }

    /**
     * 查下结果 builder
     */
    public static BeautyEscortProto.BeautyEscortCartFindTemp.Builder getSearchCartBuilder(EscortCartData cartData) {
        BeautyEscortProto.BeautyEscortCartFindTemp.Builder cartBuilder = BeautyEscortProto.BeautyEscortCartFindTemp.newBuilder();
        cartBuilder.setCartId(cartData.getCartId());
        cartBuilder.setState(cartData.getState());
        cartBuilder.setTypeId(cartData.getDartTypeId());
        cartBuilder.addAllBeauty(parseBeautyDispatchBuilderList(cartData.getBeautyDispatchList()));
        cartBuilder.setDartId(cartData.getDartId());
        return cartBuilder;
    }

    /**
     * 商会榜单
     */
    public static List<BeautyEscortProto.BeautyEscortUnionWeekRankTempMsg> parseUnionRankListMsg(LinkedList<CrossUnionWeekRank> rankList) {
        List<BeautyEscortProto.BeautyEscortUnionWeekRankTempMsg> result = new ArrayList<>();
        int size = rankList.size();
        for (int i = 0; i < size; i++) {
            CrossUnionWeekRank unionWeekRank = rankList.get(i);
            BeautyEscortProto.BeautyEscortUnionWeekRankTempMsg.Builder builder = BeautyEscortProto.BeautyEscortUnionWeekRankTempMsg.newBuilder();
            builder.setValue(unionWeekRank.getValue().toString());
            builder.setUnionUid(unionWeekRank.getUnionUid());
            builder.setUnionBaseData(UnionBasePb.parseUnionBaseTempMsg(unionWeekRank.getUnionBaseInfo()));
            result.add(builder.build());
        }
        return result;
    }

    /**
     * 构建美女派遣
     */
    public static BeautyEscortProto.BeautyEscortBeautyDispatchDataTemp.Builder getBeautyDispatchBuilder(int beautyId, int glamour) {
        BeautyEscortProto.BeautyEscortBeautyDispatchDataTemp.Builder dispatchBuilder = BeautyEscortProto.BeautyEscortBeautyDispatchDataTemp.newBuilder();
        dispatchBuilder.setBeautyId(beautyId);
        dispatchBuilder.setGlamour(glamour);
        return dispatchBuilder;
    }

    /**
     * 获取NPC Cart
     */
    public static BeautyEscortProto.BeautyEscortCartTemp.Builder getBeautyEscortCartTemp(EscortBeautyCartNPCInfo npcCart){
        BeautyEscortProto.BeautyEscortCartTemp.Builder builder = BeautyEscortProto.BeautyEscortCartTemp.newBuilder();
        builder.setCartId(npcCart.getId());
        builder.setDartId(0);
        builder.setState(eEscortCartState.Escorting.getIntValue());
        builder.setEventHandle(true);
        builder.setStartTime(DateHelper.getCurrentSecond());
        builder.setCartType(npcCart.getType());
        for (int beautyId : npcCart.getBeautyList()) {
            builder.addBeauty(getBeautyDispatchBuilder(beautyId, npcCart.getGlamour()));
        }
        return builder;
    }

    /**
     * 路线地图-玩家-简要信息
     */
    public static BeautyEscortProto.BeautyEscortCartSimpleTemp.Builder getCartSimpleBuilder(EscortCartData cartData) {
        BeautyEscortProto.BeautyEscortCartSimpleTemp.Builder builder = BeautyEscortProto.BeautyEscortCartSimpleTemp.newBuilder();
        builder.setCartId(cartData.getCartId());
        builder.setState(cartData.getState());
        builder.setGetReward(cartData.isGetReward());
        builder.setEventHandle(cartData.getEvent().isEnd());
        builder.setStartTime(cartData.getStartTime());
        builder.setClientId(cartData.getClientId());
        builder.setTypeId(cartData.getDartTypeId());
        builder.setDartId(cartData.getDartId());
        builder.setGetEventReward(cartData.isGetEventReward());
        builder.setEventId(cartData.getEvent().getEventId());
        builder.addAllRobUser(cartData.getEnemy().subList(0, Math.min(cartData.getEnemy().size(), ConfigMgr.getMaxRobTimesInLoss())));
        builder.setReduceTime(cartData.getReduceTime());
        return builder;
    }

    /**
     * 路线地图-NPC玩家-简要信息
     */
    public static BeautyEscortProto.BeautyEscortCartSimpleTemp.Builder getCartSimpleBuilder(EscortBeautyCartNPCInfo npcCart) {
        BeautyEscortProto.BeautyEscortCartSimpleTemp.Builder builder = BeautyEscortProto.BeautyEscortCartSimpleTemp.newBuilder();
        builder.setCartId(npcCart.getId());
        builder.setState(eEscortCartState.Escorting.getIntValue());
        builder.setGetReward(false);
        builder.setEventHandle(true);
        builder.setStartTime(DateHelper.getCurrentSecond());
        builder.setClientId(npcCart.getClientId());
        builder.setTypeId(npcCart.getType());
        builder.setDartId(0);
        builder.setEventId(0);
        builder.setGetEventReward(true);
        return builder;
    }

    public static void repair(long userId, String param){
        logger.info("repair {} {}", userId, param);


    }
}
